﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Remoting.Messaging;
using uCoreClasses;
using UnityCore;

namespace StoreClientModule
{
    public struct NodeType
    {
        public string Key;
        public string Value;
    }
    public struct SettingType
    {
        public string Section;
        public NodeType[] Node;
    }
    public struct UpdateType
    {
        public string fUpdateKey;
        public string fFlag;
        public string fRemarks;
    }
    public struct UploadType
    {
        public string fUpdateKey;
        public string fPKey;
        public string fParentTable;
        public string fParentKey;
        public string fRemarks;
        public string fFlag;
    }
    static class Common
    {
        //Local Connection
        public static string lUID = "";
        public static string lPWD = "";
        public static string lDatabase = "";
        public static string lServer = "";
        public static string lStoreID = "";
        public static string lStoreName = "";
        public static string lStoreAddress = "";

        //Online Connection
        public static string oUID = "";
        public static string oPWD = "";
        public static string oDatabase = "";
        public static string oServer = "";
        //Update Buffer
        public static UpdateType[] Updates = new UpdateType[0];
        public static UploadType[] Uploads = new UploadType[0];
        //User
        public static string Username = "";
        public static string Password = "";
        public static bool UserLogged = false;
        public static float GetVolumeFactor(string fBase, string fTo)
        {
            float retVal = 0f;
            //Indices
            int x = -1, y = -1;
            //Volume Table
            string[] bV = { "LTR", "ML", "GAL" };
            string[] tV = { "LTR", "ML", "GAL" };
            float[][] vV = new float[3][];
            vV[0] = new float[] { 1f, 1000f, 0.25f };
            vV[1] = new float[] { 0.001f, 1f, 0.00025f };
            vV[2] = new float[] { 4f, 4000f, 1f };

            for (int i = 0; i < bV.Length; i++)
            {
                if (fBase == bV[i])
                {
                    x = i;
                    break;
                }
            }
            for (int i = 0; i < tV.Length; i++)
            {
                if (fTo == tV[i])
                {
                    y = i;
                    break;
                }
            }
            if (x == -1 || y == -1)
            {
                retVal = -1f;
            }
            else
            {
                retVal = vV[x][y];
            }
            return retVal;
        }
        public static float GetWeightFactor(string fBase, string fTo)
        {
            float retVal = 0f;
            //Indices
            int x = -1, y = -1;
            //Weight Table
            string[] bV = { "KG", "G" };
            string[] tV = { "KG", "G" };
            float[][] vV = new float[2][];
            vV[0] = new float[] { 1f, 1000f };
            vV[1] = new float[] { 0.001f, 1f };

            for (int i = 0; i < bV.Length; i++)
            {
                if (fBase == bV[i])
                {
                    x = i;
                    break;
                }
            }
            for (int i = 0; i < tV.Length; i++)
            {
                if (fTo == tV[i])
                {
                    y = i;
                    break;
                }
            }
            if (x == -1 || y == -1)
            {
                retVal = -1f;
            }
            else
            {
                retVal = vV[x][y];
            }
            return retVal;
        }
        public static float GetLengthFactor(string fBase, string fTo)
        {
            float retVal = 0f;
            //Indices
            int x = -1, y = -1;
            //Length Table
            string[] bV = { "M", "F" };
            string[] tV = { "M", "F" };
            float[][] vV = new float[2][];
            vV[0] = new float[] { 1f, 3.28f };
            vV[1] = new float[] { 0.3048f, 1f };

            for (int i = 0; i < bV.Length; i++)
            {
                if (fBase == bV[i])
                {
                    x = i;
                    break;
                }
            }
            for (int i = 0; i < tV.Length; i++)
            {
                if (fTo == tV[i])
                {
                    y = i;
                    break;
                }
            }
            if (x == -1 || y == -1)
            {
                retVal = -1f;
            }
            else
            {
                retVal = vV[x][y];
            }
            return retVal;
        }
        public static string FormatCurrency(string value)
        {
            string res = "";
            try
            {
                float val = float.Parse(value);
                res = val.ToString("#,0.00");
            }
            catch (Exception ex)
            {
            }
            return res;
        }
        public static string FormatCurrency(double num)
        {
            string value = "";
            try
            {
                value = num.ToString("#,#0.00");
            }
            catch (Exception ex)
            {
                value = ex.Message;
            }
            return value;
        }
        public static string FormatPercent(string value)
        {
            string res = "";
            try
            {
                float val = float.Parse(value);
                res = val.ToString("#0.00");
            }
            catch (Exception ex)
            {
            }
            return res;
        }
        public static string FormatNumber(string value)
        {
            string res = "";
            try
            {
                float val = float.Parse(value);
                res = val.ToString("#,#.##");
            }
            catch (Exception ex)
            {
            }
            return res;
        }
        public static string FormatEquivalent(string value)
        {
            char[] equi = { 'K', 'S', 'A', 'N', 'Y', 'O', 'Q', 'U', 'I', 'C' };
            char[] cArr = value.ToCharArray();
            int[] ibuf = new int[cArr.Length];
            string res = "";
            for (int i = 0; i < cArr.Length; i++)
            {
                if (cArr[i] != ',' && cArr[i] != '.')
                {
                    ibuf[i] = int.Parse(cArr[i].ToString());
                    res += equi[ibuf[i]];
                }
                else if (cArr[i] == '.')
                {
                    res += ".";
                }

            }
            return res;
        }
        public static string[] ListFinder(string[] lst, string str)
        {
            List<string> lt = new List<string>();
            lt.AddRange(lst);
            SearchDel search = dat =>
            {
                string[] l;
                l = lt.FindAll(n => n.Contains(dat)).ToArray();
                return l;
            };
            return search(str);
        }
        public static void WriteSettings(SettingType[] cfg)
        {
            using (StreamWriter sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\\MBBClient.Txt"))
            {
                try
                {
                    string dat = "";
                    for (int i = 0; i < cfg.Length; i++)
                    {
                        dat += "[" + cfg[i].Section + "]\r\n";
                        for (int j = 0; j < cfg[i].Node.Length; j++)
                        {
                            dat += cfg[i].Node[j].Key + "=" + cfg[i].Node[j].Value + "\r\n";
                        }
                    }

                    sw.Write(dat);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    sw.Close();
                }
            }
        }
        public static SettingType[] ReadSettings()
        {
            SettingType[] cfg = new SettingType[0];
            string dat = "", str = "";
            int NewSect = 0, NewNode = 0;
            using (StreamReader sr = new StreamReader(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\MBBClient.Txt"))
            {
                try
                {
                    while ((str = sr.ReadLine()) != null)
                    {
                        if (str.StartsWith("["))
                        {
                            NewSect = cfg.Length + 1;
                            NewNode = 0;
                            Array.Resize<SettingType>(ref cfg, NewSect);
                            cfg[NewSect - 1].Section = str.Substring(1, str.Length - 2);
                        }
                        else if (!str.StartsWith("[") && cfg.Length > 0 && !str.Equals(""))
                        {
                            if (NewNode == 0)
                            {
                                cfg[NewSect - 1].Node = new NodeType[0];
                            }
                            NewNode = cfg[NewSect - 1].Node.Length + 1;
                            Array.Resize<NodeType>(ref cfg[NewSect - 1].Node, NewNode);
                            string[] buf = new string[2];
                            string s = "";
                            for (int i = 0; i < str.Length; i++)
                            {
                                s = str.Substring(i, 1);
                                if (!s.Equals("="))
                                {
                                    buf[0] += s;
                                }
                                else
                                {
                                    i++;
                                    buf[1] = str.Substring(i);
                                    break;
                                }
                            }
                            cfg[NewSect - 1].Node[NewNode - 1].Key = buf[0];
                            cfg[NewSect - 1].Node[NewNode - 1].Value = buf[1];
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    sr.Close();
                }
                return cfg;
            }
        }
        public static MBBStoreClient.frmMain parent;
    }
    public delegate string[] SearchDel(string dat);
    public delegate void ModuleEventHandler(string procCode, string msg);
    public delegate void ModuleEventsHandler(int procCode, string msg);

    //MBB_Client
    public struct ProcessType
    {
        public string ID;
        public string Message;
        public bool HasError;
    }
    public struct SalesItemType
    {
        public string fInvoice;
        public string fBarcode;
        public string fQty;
        public string fUnit;
        public string fDescription;
        public string fUnitPrice;
        public string fContentBarcode;
        public string fContentQty;
        public string fContentUnit;

    }
    public struct SalesType
    {
        public string fStoreID;
        public string fSoldTo;
        public string fAddress;
        public string fTelNo;
        public string fSalesman;
        public string fRef;
        public string fTerms;
        public string fPercentage;
        public string fORNum;
        public string fInvoice;
        public string fInvoiceType;
        public string fDate;
        public string fPO;
        public SalesItemType[] Items;
        public SalesItemType[] SubItems;
    }
    public struct SalesAmountType
    {
        public string fInvoice;
        public string fAmount;
    }
    public struct DailySalesType
    {
        public string fDate;
        public string fSalesman;
        public string fTotal;
        public SalesAmountType[] fSale;
    }
    public struct UserType
    {
        public string Username;
        public string Password;
        public bool logged;
    }
    public struct StockType
    {
        public string fBarcode;
        public int fQty;
    }
    public struct ContentDetailType
    {
        public string fBarcode;
        public string fUnit;
        public string fQty;
    }
    public struct SetUpdateIndividualType
    {
        public string date;
        public int index;
    }

    public struct soldToInfo
    {
        public string refNum;
        public string address;
        public string telNo;
        public string[] referenceNumber;
    }
    //Modules
    public class Sync
    {   //Sync Operations
        void pCheckUpdate(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "CheckUpdate";
            try
            {
                uDatabase db = new uDatabase();
                db.TimeOut = 15;
                UpdateType[] ut = new UpdateType[0];
                Common.Updates = new UpdateType[0];
                OnProcessUpdate(er.ID, "Preparing data update request...");
                
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT * FROM tblUpdates");
                db.Disconnect();
                if (db.Count > 0)
                {
                    ut = new UpdateType[db.Count];
                    for (int i = 0; i < db.Count; i++)
                    {
                        ut[i].fUpdateKey = db.RecordAt(i, "fUpdateKey");
                        ut[i].fFlag = db.RecordAt(i, "fFlag");
                    }
                    OnProcessUpdate(er.ID, "Requesting data update...");
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.oServer, "malolos_mbb_online", Common.oUID, Common.oPWD);
                    db.RecordQuery("SELECT * FROM tblUpdates");
                    OnProcessUpdate(er.ID, "Getting update status...");
                    if (db.Count > 0)
                    {
                        for (int i = 0; i < ut.Length; i++)
                        {
                            if (!ut[i].fFlag.Equals(db.RecordAt(i, "fFlag")))
                            {
                                int l = Common.Updates.Length + 1;
                                Array.Resize<UpdateType>(ref Common.Updates, l);
                                Common.Updates[l - 1].fUpdateKey = db.RecordAt(i, "fUpdateKey");
                                Common.Updates[l - 1].fFlag = db.RecordAt(i, "fFlag");
                                Common.Updates[l - 1].fRemarks = db.RecordAt(i, "fRemarks");
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                //er.Message = "Update check error.";
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        void pGetUpdate(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "GetUpdate";
            try
            {
                uDatabase db = new uDatabase();
                db.TimeOut = 15;
                for (int u = 0; u < Common.Updates.Length; u++)
                {
                    //Fill in the update table with data.
                    OnProcessUpdate(er.ID, Common.Updates[u].fRemarks + " - Downloading data from update server...");
                    db.Disconnect();
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.oServer, "malolos_mbb_online", Common.oUID, Common.oPWD);
                    db.RecordQuery("SELECT * FROM " + Common.Updates[u].fUpdateKey);
                    db.Disconnect();
                    OnProcessUpdate(er.ID, Common.Updates[u].fRemarks + " - Constructing data structure...");
                    DataTable upd = new DataTable();
                    for (int i = 0; i < db.QueryTable.Columns.Count; i++)
                    {
                        upd.Columns.Add(db.QueryTable.Columns[i].ToString());
                    }
                    for (int i = 0; i < db.QueryTable.Rows.Count; i++)
                    {
                        DataRow dr = upd.NewRow();
                        for (int j = 0; j < dr.ItemArray.Length; j++)
                        {
                            dr[j] = db.RecordAt(i, j);
                            string str = dr[j].ToString();
                        }
                        upd.Rows.Add(dr);
                    }
                    //Delete the current contents of the table
                    OnProcessUpdate(er.ID, Common.Updates[u].fRemarks + " - Preparing data buffers...");
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                    db.RecordQuery("SELECT * FROM " + Common.Updates[u].fUpdateKey);
                    for (int i = 0; i < db.Count; i++)
                    {
                        db.Records[i].Delete();
                    }
                    db.Update();
                    //Add the new contents
                    OnProcessUpdate(er.ID, Common.Updates[u].fRemarks + " - Applying data updates....");
                    db.RecordQuery("SELECT * FROM " + Common.Updates[u].fUpdateKey);
                    for (int i = 0; i < upd.Rows.Count; i++)
                    {
                        DataRow dr = db.GetParameter();
                        for (int j = 0; j < dr.ItemArray.Length; j++)
                        {
                            dr[j] = upd.Rows[i][j];
                            string str = dr.ItemArray[j].ToString();
                        }
                        db.AddRecord(dr);
                    }
                    db.Update();
                    db.RecordQuery("SELECT * FROM tblUpdates WHERE fUpdateKey='" + Common.Updates[u].fUpdateKey +"'");
                    db.Records[0]["fFlag"] = Common.Updates[u].fFlag;
                    db.Update();
                    db.Disconnect();
                }
                //Clear the update flag
                OnProcessUpdate(er.ID, "Finalizing Updates...");
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
            
        }
        void pCheckUpload(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "CheckUpload";
            try
            {
                uDatabase db = new uDatabase();
                db.TimeOut = 15;
                UploadType[] ut = new UploadType[0];
                Common.Uploads = new UploadType[0];
                OnProcessUpdate(er.ID, "Preparing data upload request...");
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT * FROM tblUploads");
                db.Disconnect();
                if (db.Count > 0)
                {
                    ut = new UploadType[db.Count];
                    for (int i = 0; i < db.Count; i++)
                    {
                        ut[i].fUpdateKey = db.RecordAt(i, "fUpdateKey");
                        ut[i].fFlag = db.RecordAt(i, "fFlag");
                    }
                    OnProcessUpdate(er.ID, "Requesting data upload...");
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                    db.RecordQuery("SELECT * FROM tblUploads");
                    OnProcessUpdate(er.ID, "Getting update status...");
                    if (db.Count > 0)
                    {
                        for (int i = 0; i < ut.Length; i++)
                        {
                            int l = Common.Uploads.Length + 1;
                            Array.Resize<UploadType>(ref Common.Uploads, l);
                            Common.Uploads[l - 1].fUpdateKey = db.RecordAt(i, "fUpdateKey");
                            Common.Uploads[l - 1].fPKey = db.RecordAt(i, "fPKey");
                            Common.Uploads[l - 1].fParentTable = db.RecordAt(i, "fParentTable");
                            Common.Uploads[l - 1].fParentKey = db.RecordAt(i, "fParentKey");
                            Common.Uploads[l - 1].fFlag = db.RecordAt(i, "fFlag");
                            Common.Uploads[l - 1].fRemarks = db.RecordAt(i, "fRemarks");
                        }
                    }
                    db.Disconnect();
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                //er.Message = "Update check error.";
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }

        void pSetUpdate(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "SetUpdate";
            try
            {
                uDatabase db = new uDatabase();
                db.TimeOut = 15;
                string sdate = (string)p;
                
                for (int u = 0; u < Common.Uploads.Length; u++)
                {
                    //Fill in the update table with data.
                    OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Preparing data for upload...");
                    db.Disconnect();
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                    if (Common.Uploads[u].fParentTable.Equals(""))
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                    }
                    else
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                    }
                    db.Disconnect();
                    if (db.Count > 0)
                    {
                        OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Constructing data structure...");
                        DataTable upd = new DataTable();
                        for (int i = 0; i < db.QueryTable.Columns.Count; i++)
                        {
                            upd.Columns.Add(db.QueryTable.Columns[i].ToString());
                            OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " Build col " + i);
                        }
                        for (int i = 0; i < db.QueryTable.Rows.Count; i++)
                        {
                            DataRow dr = upd.NewRow();
                            for (int j = 0; j < dr.ItemArray.Length; j++)
                            {
                                dr[j] = db.RecordAt(i, j);
                                string str = dr[j].ToString();
                            }
                            upd.Rows.Add(dr);
                            OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " Add Row " + i);
                        }
                        //Delete the current contents of the table
                        OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Preparing data buffers...");
                        db.Connect(uCoreClasses.OdbcVersion.v510, Common.oServer, Common.oDatabase, Common.oUID, Common.oPWD);
                        if (Common.Uploads[u].fParentTable.Equals(""))
                        {
                            db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                        }
                        else
                        {
                            db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                        }
                        for (int i = 0; i < db.Count; i++)
                        {
                            db.Records[i].Delete();
                            OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " Delete " + i);
                        }
                        db.Update();
                        //Add the new contents
                        OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Uploading data updates....");
                        if (Common.Uploads[u].fParentTable.Equals(""))
                        {
                            db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                        }
                        else
                        {
                            db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                        } 
                        for (int i = 0; i < upd.Rows.Count; i++)
                        {
                            DataRow dr = db.GetParameter();
                            for (int j = 0; j < dr.ItemArray.Length; j++)
                            {
                                dr[j] = upd.Rows[i][j];
                                string str = dr.ItemArray[j].ToString();
                            }
                            OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " Add Online " + i);
                            db.AddRecord(dr);
                        }
                        db.Update();
                        db.Disconnect();
                    }
                }
                //Clear the update flag
                OnProcessUpdate(er.ID, "Upload(s) Complete...");
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }

        }
        void pSetUpdateIndividual(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "SetUpdateIndividual";
            SetUpdateIndividualType sit = (SetUpdateIndividualType)p;
            int u = sit.index;
            string sdate = sit.date;
            //Fill in the update table with data.
            try
            {
                uDatabase db = new uDatabase();
                db.TimeOut = 15;
                OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Preparing data for upload...");
                db.Disconnect();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                if (Common.Uploads[u].fParentTable.Equals(""))
                {
                    db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                }
                else
                {
                    db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                }
                db.Disconnect();
                if (db.Count > 0)
                {
                    OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Constructing data structure...");
                    DataTable upd = new DataTable();
                    for (int i = 0; i < db.QueryTable.Columns.Count; i++)
                    {
                        upd.Columns.Add(db.QueryTable.Columns[i].ToString());
                    }
                    for (int i = 0; i < db.QueryTable.Rows.Count; i++)
                    {
                        DataRow dr = upd.NewRow();
                        for (int j = 0; j < dr.ItemArray.Length; j++)
                        {
                            dr[j] = db.RecordAt(i, j);
                            string str = dr[j].ToString();
                        }
                        upd.Rows.Add(dr);
                    }
                    //Delete the current contents of the table
                    OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Preparing data buffers...");
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.oServer, Common.oDatabase, Common.oUID, Common.oPWD);
                    if (Common.Uploads[u].fParentTable.Equals(""))
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                    }
                    else
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                    }
                    for (int i = 0; i < db.Count; i++)
                    {
                        db.Records[i].Delete();
                    }
                    db.Update();
                    //Add the new contents
                    OnProcessUpdate(er.ID, Common.Uploads[u].fRemarks + " - Uploading data updates....");
                    if (Common.Uploads[u].fParentTable.Equals(""))
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                    }
                    else
                    {
                        db.RecordQuery("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                    }
                    for (int i = 0; i < upd.Rows.Count; i++)
                    {
                        DataRow dr = db.GetParameter();
                        for (int j = 0; j < dr.ItemArray.Length; j++)
                        {
                            dr[j] = upd.Rows[i][j];
                            string str = dr.ItemArray[j].ToString();
                        }
                        db.AddRecord(dr);
                    }
                    db.Update();
                    db.Disconnect();
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        void pSetUpdate_v2(object p, out object e)
        {
            OdbcAccess db = new OdbcAccess(new OdbcDetails() { DB = "mbbclient_database", SVR = "localhost", VER = UnityCore.OdbcVersion.v510, UID = Common.lUID, PWD = Common.lPWD });
            //UnityProcess proc = new UnityProcess(){ID = "SetUpdate"};
            ProcessType proc = new ProcessType() { ID = "SetUpdate" };
            string sdate = (string)p;
            try
            {
                for (int u = 0; u < Common.Uploads.Length; u++)
                {
                    OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Preparing data for upload...");
                    //db.Disconnect();
                    db.SetDetails(new OdbcDetails(){DB = "mbbclient_database", SVR = "localhost", VER = UnityCore.OdbcVersion.v510, UID = Common.lUID, PWD = Common.lPWD });
                    db.Connect();
                    if (Common.Uploads[u].fParentTable.Equals(""))
                    {
                        db.Query("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                        OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Preparing data for upload..." + db.Count);
                    }
                    else
                    {
                        db.Query("SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "'");
                        string quer = "SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " ;
                        for (int i = 0; i < db.Count; i++)
                        {
                            quer += Common.Uploads[u].fPKey+"='" + db.GetField(i, Common.Uploads[u].fPKey) + "'";
                            if (i != db.Count - 1) quer += " OR ";
                        }
                        db.Query(quer);
                        OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Preparing data for upload..."+db.Count);
                    }
                    if (db.Count > 0)
                    {
                        OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Constructing data structure..." + db.Count);
                        //load buffer the content of the table
                        DataTable upd = new DataTable();
                        db.Export(ref upd);
                        db.Disconnect();
                        //Delete the current contents of the table
                        OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Preparing data buffers..." + db.Count);
                        db.SetDetails(new OdbcDetails { DB = Common.oDatabase, SVR = Common.oServer, VER = UnityCore.OdbcVersion.v510, UID = Common.oUID, PWD = Common.oPWD });
                        db.Connect();
                        if (Common.Uploads[u].fParentTable.Equals(""))
                        {
                            db.Query("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                        }
                        else
                        {
                            //db.Query("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                            db.Query("SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "'");
                            string quer2 = "SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE ";
                            for (int i = 0; i < db.Count; i++)
                            {
                                quer2 += Common.Uploads[u].fPKey + "='" + db.GetField(i, Common.Uploads[u].fPKey) + "'";
                                if (i != db.Count - 1) quer2 += " OR ";
                            }
                            db.Query(quer2);
                        }
                        db.Delete(0, db.Count - 1);
                        db.Commit();
                        //Add the new contents
                        OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " - Uploading data updates....");
                        if (Common.Uploads[u].fParentTable.Equals(""))
                        {
                            db.Query("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + "='" + sdate + "'");
                        }
                        else
                        {
                            //db.Query("SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE " + Common.Uploads[u].fPKey + " IN (SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "')");
                            db.Query("SELECT " + Common.Uploads[u].fPKey + " FROM " + Common.Uploads[u].fParentTable + " WHERE " + Common.Uploads[u].fParentKey + "='" + sdate + "'");
                            string quer3 = "SELECT * FROM " + Common.Uploads[u].fUpdateKey + " WHERE ";
                            for (int i = 0; i < db.Count; i++)
                            {
                                quer3 += Common.Uploads[u].fPKey + "='" + db.GetField(i, Common.Uploads[u].fPKey) + "'";
                                if (i != db.Count - 1) quer3 += " OR ";
                            }
                            db.Query(quer3);
                        }
                        for (int i = 0; i < upd.Rows.Count; i++)
                        {
                            DataRow dr = db.GetSchema();
                            for (int j = 0; j < dr.ItemArray.Length; j++)
                            {
                                dr[j] = upd.Rows[i][j];
                                OnProcessUpdate(proc.ID, Common.Uploads[u].fRemarks + " Add Online " + i);
                            }
                            db.Add(dr);
                        }
                        db.Commit();
                        OnProcessUpdate(proc.ID, "Upload(s) Complete...");
                        db.Disconnect();
                    }
                    else
                    {
                        db.Disconnect();
                    }
                }
            }
            catch (Exception ex)
            {
                proc.HasError = true;
                proc.Message = ex.Message;
            }
            finally
            {
                e = proc;
            }
        }
        
       
        //Async Operation
        delegate void AsyncOp(object p, out object e);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (!((ProcessType)er).HasError)
            {
                OnProcessCompleted(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
            else
            {
                OnProcessError(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
        }

        public void CheckUpdate()
        {
            AsyncOp ao = new AsyncOp(pCheckUpdate);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(null, out er, ac, null);
        }
        public void GetUpdate()
        {
            AsyncOp ao = new AsyncOp(pGetUpdate);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(null, out er, ac, null);
        }
        public void CheckUpload()
        {
            AsyncOp ao = new AsyncOp(pCheckUpload);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(null, out e, ac, null);
        }
        public void SetUpdate(string date)
        {
            AsyncOp ao = new AsyncOp(pSetUpdate_v2);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(date,out e, ac, null);
        }
        public void SetUpdate(SetUpdateIndividualType sit)
        {
            AsyncOp ao = new AsyncOp(pSetUpdateIndividual);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(sit, out e, ac, null);
        }
        //Event
        public event ModuleEventHandler ProcessCompleted;
        public event ModuleEventHandler ProcessError;
        public event ModuleEventHandler ProcessUpdate;
        protected virtual void OnProcessError(string procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected virtual void OnProcessCompleted(string procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
        protected virtual void OnProcessUpdate(string procCode, string msg)
        {
            if (ProcessUpdate != null) ProcessUpdate(procCode, msg);
        }
    }
    public class PriceListViewer
    {
        private DataTable pPriceList = new DataTable();
        private DataTable pSearchList = new DataTable();
        //Sync Operation
        void pGetPriceList(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "GetPriceList";
            try
            {
                pPriceList = new DataTable();
                //fSupplier, fBarcode, fDescription, fVariation, fP.Code, fMarkUp
                DataTable dt = new DataTable();
                dt.Columns.Add("fSupplier");
                dt.Columns.Add("fBarcode");
                dt.Columns.Add("fDescription");

                //pPriceList.Columns.Add("fSupplier");
                pPriceList.Columns.Add("fBarcode");
                pPriceList.Columns.Add("fDescription");
                pPriceList.Columns.Add("fVariation");
                pPriceList.Columns.Add("fPcode");
                pPriceList.Columns.Add("fMarkUp");

                DataRow dr0 = pPriceList.NewRow();
                //dr0["fSupplier"] = "Supplier";
                dr0["fBarcode"] = "Barcode";
                dr0["fDescription"] = "Description";
                dr0["fVariation"] = "Variation";
                dr0["fPcode"] = "P.Code";
                dr0["fMarkUp"] = "SRP";
                pPriceList.Rows.Add(dr0);

                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT * FROM tblProducts ORDER BY fSupplier ASC, fDescription ASC");
                if (db.Count > 0)
                {
                    for (int i = 0; i < db.Count; i++)
                    {
                        DataRow dr = dt.NewRow();
                        dr["fSupplier"] = db.RecordAt(i, "fSupplier");
                        dr["fBarcode"] = db.RecordAt(i, "fBarcode");
                        dr["fDescription"] = db.RecordAt(i, "fDescription");
                        dt.Rows.Add(dr);
                    }
                    db.RecordQuery("SELECT fVariation, fPcode, fMarkUp, fBarcode FROM tblPriceList ORDER BY fBarcode ASC");
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {

                        if (i > 0)
                        {
                            if (dt.Rows[i - 1]["fSupplier"].ToString() != dt.Rows[i]["fSupplier"].ToString())
                            {
                                DataRow dr = pPriceList.NewRow();
                                dr["fBarcode"] = "Supplier :";
                                dr["fDescription"] = dt.Rows[i]["fSupplier"];
                                pPriceList.Rows.Add(dr);
                            }
                        }
                        else
                        {
                            DataRow dr = pPriceList.NewRow();
                            dr["fBarcode"] = "Supplier :";
                            dr["fDescription"] = dt.Rows[i]["fSupplier"];
                            pPriceList.Rows.Add(dr);
                        }
                        DataRow dr1 = pPriceList.NewRow();
                        dr1 = pPriceList.NewRow();
                        dr1["fBarcode"] = dt.Rows[i]["fBarcode"];
                        dr1["fDescription"] = dt.Rows[i]["fDescription"];
                        pPriceList.Rows.Add(dr1);
                        string[] fVar = new string[0];
                        string[] fMup = new string[0];
                        string[] fPc = new string[0];
                        for (int j = 0; j < db.Count; j++)
                        {
                            if (db.RecordAt(j, "fBarcode") == dt.Rows[i]["fBarcode"].ToString())
                            {
                                Array.Resize<string>(ref fVar, fVar.Length + 1);
                                Array.Resize<string>(ref fMup, fMup.Length + 1);
                                Array.Resize<string>(ref fPc, fPc.Length + 1);
                                int ind = fVar.Length - 1;
                                fVar[ind] = db.RecordAt(j, "fVariation");
                                fMup[ind] = db.RecordAt(j, "fMarkUp");
                                fPc[ind] = db.RecordAt(j, "fPCode");
                            }
                        }
                        if (fVar.Length > 0)
                        {
                            for (int j = 0; j < fVar.Length; j++)
                            {
                                DataRow dr2 = pPriceList.NewRow();
                                dr2["fVariation"] = fVar[j]; //db.RecordAt(cRow, "fVariation");
                                dr2["fPcode"] = Common.FormatEquivalent(fPc[j]); //General.FormatEquivalent(db.RecordAt(cRow, "fPCode"));
                                float percent = float.Parse(fMup[j]) / 100f;//float.Parse(db.RecordAt(cRow, "fMarkUp")) / 100f;
                                float pcode = float.Parse(fPc[j]);//float.Parse(db.RecordAt(cRow, "fPCode"));
                                float mu = (pcode * percent) + pcode;
                                dr2["fMarkUp"] = Common.FormatCurrency(mu.ToString());
                                pPriceList.Rows.Add(dr2);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        
        //Async Operation
        delegate void AsyncOp(object param, out object err);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (!((ProcessType)er).HasError)
            {
                OnProcessCompleted(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
            else
            {
                OnProcessError(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
        }

        public void GetPriceList()
        {
            AsyncOp ao = new AsyncOp(pGetPriceList);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(null, out err, ac, null);
        }
        public DataTable PriceTable
        {
            get { return pPriceList; }
        }
        //Event
        public event ModuleEventHandler ProcessCompleted;
        public event ModuleEventHandler ProcessError;
        protected virtual void OnProcessError(string procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected virtual void OnProcessCompleted(string procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
    }
    public class SalesEntry
    {
        //Connector
        uDatabase dbg = new uDatabase();
        //Buffers
        string[] bAutoDesc = new string[0];
        string[] bAutoUnit = new string[0];
        string[] bAutoSoldTo = new string[0];
        string[] bAutoSalesman = new string[0];
        string[] bAutoInvoiceType = new string[0];

        

        public SalesEntry()
        {
            dbg.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
        }
        //Sync Operation
        void pAutoDescription(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "AutoDescription";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                string str = (string)p;
                bAutoDesc = new string[0];
                db.RecordQuery("SELECT fDescription FROM tblProducts WHERE fDescription LIKE '%" + str + "%' ORDER BY fDescription ASC LIMIT 0, 5");
                bAutoDesc = new string[db.Count];
                for (int i = 0; i < db.Count; i++)
                {
                    bAutoDesc[i] = db.RecordAt(i, "fDescription");
                }
                db.Disconnect();
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting description autofill.";
            }
            finally
            {
                e = er;
            }
        }
        void pAutoUnit(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "AutoUnit";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                string str = (string)p;
                bAutoUnit = new string[0];
                db.RecordQuery("SELECT fUnit FROM tblUnits");
                bAutoUnit = new string[db.Count];
                for (int i = 0; i < db.Count; i++)
                {
                    bAutoUnit[i] = db.RecordAt(i, "fUnit");
                }
                db.Disconnect();
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting unit autofill.";
            }
            finally
            {
                e = er;
            }
        }
        void pAutoSoldTo(object p, out object e) 
        {
            ProcessType er = new ProcessType();
            er.ID = "AutoSoldTo";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                string str = (string)p;
                bAutoSoldTo = new string[0];
                db.RecordQuery("SELECT DISTINCT fSoldTo FROM tblProfile WHERE fSoldTo LIKE '%" + str + "%' ORDER BY fSoldTo ASC LIMIT 0, 5");
                bAutoSoldTo = new string[db.Count];
                for (int i = 0; i < db.Count; i++)
                {
                    bAutoSoldTo[i] = db.RecordAt(i, "fSoldTo");
                }
                db.Disconnect();
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting soldto autofill.";
            }
            finally
            {
                e = er;
            }
        }
        public soldToInfo soldInfo = new soldToInfo();
        void pGetSoldToInfo(object p, out object e)
        {
           
            ProcessType er = new ProcessType();
            er.ID = "GetSoldToInfo";
            
            uDatabase db = new uDatabase();
            string str = (string)p;
            try
            {
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT * FROM tblProfile WHERE fSoldTo = '" + str + "' AND fRef LIKE 'A%'");
                if (db.Count == 1)
                {
                    soldInfo.address = db.RecordAt(0, "fAddress");
                    soldInfo.refNum = db.RecordAt(0, "fRef");
                    soldInfo.telNo = db.RecordAt(0, "fTelNo");
                }
                else
                {
                    soldInfo.address = "Please add profile";
                    soldInfo.refNum = "Please add profile";
                    soldInfo.telNo = "Please add profile";
                }

            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting soldto profile.";
            }
            finally
            {
                e = er;
            }
        }
        void pGetSoldToInfoCharge(object p, out object e)
        {

            ProcessType er = new ProcessType();
            er.ID = "GetSoldToInfo";

            uDatabase db = new uDatabase();
            string str = (string)p;
            try
            {
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT * FROM tblProfile WHERE fSoldTo = '" + str + "' AND fRef LIKE 'B%'");
                if (db.Count == 1)
                {
                    soldInfo.address = db.RecordAt(0, "fAddress");
                    soldInfo.refNum = db.RecordAt(0, "fRef");
                    soldInfo.telNo = db.RecordAt(0, "fTelNo");
                }
                else
                {
                    soldInfo.address = "Please add profile";
                    soldInfo.refNum = "Please add profile";
                    soldInfo.telNo = "Please add profile";
                }

            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting soldto profile.";
            }
            finally
            {
                e = er;
            }
        }
        void pAutoSalesman(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "AutoSalesman";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                string str = (string)p;
                bAutoSalesman = new string[0];
                db.RecordQuery("SELECT DISTINCT fSalesman FROM tblSalesDetail WHERE fSalesman LIKE '%" + str + "%' ORDER BY fSalesman ASC LIMIT 0, 5");
                bAutoSalesman = new string[db.Count];
                for (int i = 0; i < db.Count; i++)
                {
                    bAutoSalesman[i] = db.RecordAt(i, "fSalesman");
                }
                db.Disconnect();
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting salesman autofill.";
            }
            finally
            {
                e = er;
            }
        }
        void pAutoInvoiceType(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "AutoInvoiceType";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                bAutoInvoiceType = new string[0];
                db.RecordQuery("SELECT * FROM tblInvoiceType");
                bAutoInvoiceType = new string[db.Count];
                for (int i = 0; i < db.Count; i++)
                {
                    bAutoInvoiceType[i] = db.RecordAt(i, "fInvoiceType");
                }
                db.Disconnect();
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = "Error getting invoice type autofill.";
            }
            finally
            {
                e = er;
            }
        }
        void pAdd(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "Add";
            try
            {
                SalesType st = (SalesType)p;
                dbg.RecordQuery("SELECT * FROM tblSalesDetail WHERE fInvoice='" + st.fInvoice + "'");
                if (dbg.Count == 0)
                {
                    DataRow dr = dbg.GetParameter();
                    dr["fStoreID"] = st.fStoreID;
                    dr["fSoldTo"] = st.fSoldTo;
                    dr["fAddress"] = st.fAddress;
                    dr["fTelNo"] = st.fTelNo;
                    dr["fSalesman"] = st.fSalesman;
                    dr["fRef"] = st.fRef;
                    dr["fPO"] = st.fPO;
                    dr["fORNum"] = st.fORNum;
                    dr["fInvoice"] = st.fInvoice;
                    dr["fInvoiceType"] = st.fInvoiceType;
                    dr["fDate"] = st.fDate;
                    dbg.AddRecord(dr);
                    dbg.Update(ConflictOption.CompareRowVersion);

                    dbg.RecordQuery("SELECT * FROM tblSalesItem");
                    uDatabase db = new uDatabase();
                    db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                    for (int i = 0; i < st.Items.Length; i++)
                    {
                        DataRow rw = dbg.GetParameter();
                        rw["fInvoice"] = st.Items[i].fInvoice;
                        rw["fQty"] = st.Items[i].fQty;
                        rw["fUnit"] = st.Items[i].fUnit;
                        rw["fDescription"] = st.Items[i].fDescription;
                        rw["fUnitPrice"] = st.Items[i].fUnitPrice;
                        dbg.AddRecord(rw);

                        //Update Stocks
                        
                        dbg.Update();
                    }
                }
                else
                {
                    er.HasError = true;
                    er.Message = "Duplicate invoice exist!";
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        void pAddMix(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "AddMix";
            try
            {
                //Update Stocks

                SalesType st = (SalesType)p;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                for (int i = 0; i < st.Items.Length; i++)
                {
                    if (st.Items[i].fContentBarcode != null && st.Items[i].fDescription != null)
                    {
                        float diff = 0f;
                        float cnt = 0f;
                        int ded = 0;
                        db.RecordQuery("SELECT * FROM tblStocks2 WHERE fDescription='" + st.Items[i].fDescription + "'");
                        float q1 = 0f;
                        float q2 = 0f;
                        try
                        {
                            switch (st.Items[i].fContentUnit)
                            {
                                case "LTR":
                                case "GAL":
                                case "ML":
                                    q2 = float.Parse(st.Items[i].fQty) * Common.GetVolumeFactor(st.Items[i].fUnit, st.Items[i].fContentUnit);
                                    break;
                                case "KG":
                                case "G":
                                    q2 = float.Parse(st.Items[i].fQty) * Common.GetWeightFactor(st.Items[i].fUnit, st.Items[i].fContentUnit);
                                    break;
                                case "KL":
                                    st.Items[i].fContentUnit = "KG";
                                    q2 = float.Parse(st.Items[i].fQty) * Common.GetWeightFactor(st.Items[i].fUnit, "KG");
                                    break;
                                case "M":
                                case "F":
                                    q2 = float.Parse(st.Items[i].fQty) * Common.GetLengthFactor(st.Items[i].fUnit, st.Items[i].fContentUnit);
                                    break;
                                case "MTR":
                                    st.Items[i].fContentUnit = "M";
                                    q2 = float.Parse(st.Items[i].fQty) * Common.GetLengthFactor(st.Items[i].fUnit, "M");
                                    break;
                                default:
                                    st.Items[i].fContentUnit = "N\\A";
                                    q2 = float.Parse(st.Items[i].fQty);
                                    break;
                            }
                        }
                        catch (Exception ex)
                        {
                            q2 = 0f;
                        }
                        if (db.Count == 1)
                        {
                            string str = db.RecordAt(0, "fQty");
                            if (str != null)
                            {
                                if (!float.TryParse(str, out q1)) q1 = 0;
                            }
                            else
                            {
                                q1 = 0;
                            }
                        }
                        else if (db.Count == 0)
                        {
                            q1 = 0f;
                            DataRow cdr = db.GetParameter();
                            cdr["fDescription"] = st.Items[i].fDescription;
                            cdr["fBarcode"] = st.Items[i].fContentBarcode;
                            cdr["fQty"] = "0";
                            cdr["fUnit"] = st.Items[i].fContentUnit;
                            db.AddRecord(cdr);
                            db.Update();
                            db.RecordQuery("SELECT * FROM tblStocks2 WHERE fDescription='" + st.Items[i].fDescription + "'");
                        }
                        if (db.Count == 1)
                        {
                            diff = q1 - q2;
                            cnt = 0f;
                            if (diff >= 0f)
                            {
                                db.QueryTable.Rows[0]["fQty"] = Common.FormatNumber(diff.ToString());
                                db.Update();
                            }
                            else
                            {
                                diff = Math.Abs(diff);
                                int it = (int)diff;
                                float fqty = diff % float.Parse(st.Items[i].fContentQty);
                                cnt += Math.Abs(it);
                                ded = (int)((cnt / float.Parse(st.Items[i].fContentQty)));
                                if (fqty > 0) ded++;
                                fqty = (ded * float.Parse(st.Items[i].fContentQty)) - diff;

                                db.QueryTable.Rows[0]["fQty"] = fqty.ToString();
                                db.Update();
                                db.RecordQuery("SELECT * FROM tblStocks WHERE fDescription='" + st.Items[i].fDescription + "'");

                                if (db.Count > 0)
                                {
                                    if (db.Count < ded) ded = db.Count;

                                    for (int j = 0; j < ded; j++)
                                    {
                                        db.QueryTable.Rows[j].Delete();
                                    }
                                    db.Update();
                                }
                                else
                                {
                                    db.RecordQuery("SELECT * FROM tblStocks2 WHERE fDescription='" + st.Items[i].fDescription + "'");
                                    db.QueryTable.Rows[0]["fQty"] = "0";
                                    db.Update();
                                }
                            }
                        }
                    }
                    
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        public ContentDetailType GetContent(string desc, string unit)
        {
            ContentDetailType cdt;
            try
            {
                dbg.RecordQuery("SELECT fBarcode, fContent, fUnit FROM tblProducts WHERE fDescription='" + desc + "'");
                if (dbg.Count == 1)
                {
                    cdt.fBarcode = dbg.RecordAt(0, "fBarcode");
                    cdt.fQty = dbg.RecordAt(0, "fContent");
                    cdt.fUnit = dbg.RecordAt(0, "fUnit").ToUpper();

                    float tmpf;
                    if (float.TryParse(cdt.fQty, out tmpf))
                    {
                        string cdtUnit = cdt.fUnit;
                        if (unit != "PCS")
                        {
                            if (cdt.fUnit.ToUpper().Contains("PCS")) cdtUnit = "PCS";
                            dbg.RecordQuery("SELECT fDefault FROM tblunits WHERE fUnit='" + unit + "' OR fUnit LIKE '" + cdtUnit + "'");
                            if (dbg.Count < 1 || dbg.Count > 2)
                            {
                                cdt.fBarcode = "N\\A";
                                cdt.fUnit = "N\\A";
                                cdt.fQty = "0";
                            }
                            else if (dbg.Count == 2)
                            {
                                //string u1 = dbg.RecordAt(0, "fDefault"), u2 = dbg.RecordAt(1, "fDefault");
                                if (dbg.RecordAt(0, "fDefault") != dbg.RecordAt(1, "fDefault"))
                                {
                                    cdt.fBarcode = "N\\A";
                                    cdt.fUnit = "N\\A";
                                    cdt.fQty = "0";
                                }
                            }
                        }
                        else
                        {
                            dbg.RecordQuery("SELECT fDefault FROM tblunits WHERE fUnit LIKE '%" + cdtUnit + "%'");
                            if (dbg.Count == 0)
                            {
                                cdt.fBarcode = "N\\A";
                                cdt.fUnit = "N\\A";
                                cdt.fQty = "0";
                            }
                        }
                    }
                    else
                    {
                        cdt.fBarcode = "N\\A";
                        cdt.fUnit = "N\\A";
                        cdt.fQty = "0";
                    }
                }
                else
                {
                    cdt.fBarcode = "N\\A";
                    cdt.fUnit = "N\\A";
                    cdt.fQty = "0";
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return cdt;
        }
        
        //Async Operation
        delegate void AsyncOp(object p, out object e);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (!((ProcessType)er).HasError)
            {
                OnProcessCompleted(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
            else
            {
                OnProcessError(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
        }

        public void Add(SalesType st)
        {
            AsyncOp ao = new AsyncOp(pAdd);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(st, out er, ac, null);
        }
        public void AddMix(SalesType st)
        {
            AsyncOp ao = new AsyncOp(pAddMix);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(st, out er, ac, null);
        }
        public void AutoDescription(string str)
        {
            AsyncOp ao = new AsyncOp(pAutoDescription);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public void AutoUnit(string str)
        {
            AsyncOp ao = new AsyncOp(pAutoUnit);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public void AutoSoldTo(string str)
        {
            AsyncOp ao = new AsyncOp(pAutoSoldTo);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public void AutoSalesman(string str)
        {
            AsyncOp ao = new AsyncOp(pAutoSalesman);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public void AutoInvoiceType()
        {
            AsyncOp ao = new AsyncOp(pAutoInvoiceType);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(null, out e, ac, null);
        }
        public void GetSoldToInfo(string str)
        {
            AsyncOp ao = new AsyncOp(pGetSoldToInfo);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public void GetSoldToInfoCharge(string str)
        {
            AsyncOp ao = new AsyncOp(pGetSoldToInfoCharge);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object e;
            IAsyncResult ar = ao.BeginInvoke(str, out e, ac, null);
        }
        public string[] ListAutoDescription
        {
            get { return bAutoDesc; }
        }
        public string[] ListAutoUnit
        {
            get { return bAutoUnit; }
        }
        public string[] ListAutoSoldTo
        {
            get { return bAutoSoldTo; }
        }
        public string[] ListAutoSalesman
        {
            get { return bAutoSalesman; }
        }
        public string[] ListAutoInvoiceType
        {
            get { return bAutoInvoiceType; }
        }

        //Event
        public event ModuleEventHandler ProcessCompleted;
        public event ModuleEventHandler ProcessError;
        protected virtual void OnProcessError(string procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected virtual void OnProcessCompleted(string procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
    }
    public class UserManager
    {
        private struct ErrorType
        {
            public int ID;
            public string Process;
            public string Message;
        }
        private static string svr = Common.lServer, dbq = Common.lDatabase, uid = Common.lUID, pwd = Common.lPWD;
        private string[] pUser = new string[0];
        private UserType pProfile = new UserType();
        //Sync Operation
        void pGetUserList(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 22;
            er.Process = "GetUserList";
            try
            {
                pUser = new string[0];
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers");
                pUser = new string[db.Count];
                if (db.Count > 0)
                {
                    for (int i = 0; i < db.Count; i++)
                    {
                        pUser[i] = db.RecordAt(i, "fUsername");
                    }
                }
            }
            catch (Exception ex)
            {
                er.ID = -22;
                er.Message = ex.Message;
                er.Process = "GetUserList";
            }
            finally
            {
                err = er;
            }
        }
        void pGetUser(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 26;
            er.Process = "GetUserList";
            try
            {
                string ut = (string)param;
                pProfile = new UserType();
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers WHERE fUsername='" + ut + "'");
                if (db.Count > 0)
                {
                    pProfile.Username = db.RecordAt(0, "fUsername");
                    pProfile.Password = db.RecordAt(0, "fPassword");
                }
            }
            catch (Exception ex)
            {
                er.ID = -26;
                er.Message = ex.Message;
                er.Process = "GetUserList";
            }
            finally
            {
                err = er;
            }
        }
        void pAdd(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 23;
            er.Process = "Add";
            try
            {
                UserType ut = (UserType)param;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers WHERE fUsername='" + ut.Username + "'");
                if (db.Count == 0)
                {
                    DataRow dr = db.GetParameter();
                    dr["fUsername"] = ut.Username;
                    dr["fPassword"] = ut.Password;
                    db.AddRecord(dr);
                    db.Update(ConflictOption.CompareRowVersion);
                }
                else
                {
                    er.ID = -23;
                    er.Message = "User already exist.";
                }
            }
            catch (Exception ex)
            {
                er.ID = -23;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        void pUpdate(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 24;
            er.Process = "Update";
            try
            {
                UserType[] ut = (UserType[])param;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers WHERE fUsername='" + ut[1].Username + "'");
                if (db.Count == 1)
                {
                    db.Records[0]["fUsername"] = ut[0].Username;
                    db.Records[0]["fPassword"] = ut[0].Password;
                    db.Update(ConflictOption.CompareRowVersion);
                }
                else
                {
                    er.ID = -24;
                    er.Message = "User already exist.";
                }
            }
            catch (Exception ex)
            {
                er.ID = -24;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        void pDelete(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 25;
            er.Process = "Update";
            try
            {
                string ut = (string)param;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers WHERE fUsername='" + ut + "'");
                if (db.Count == 1)
                {
                    db.Records[0].Delete();
                    db.Update(ConflictOption.CompareRowVersion);
                }
                else
                {
                    er.ID = -25;
                    er.Message = "User does not exist.";
                }
            }
            catch (Exception ex)
            {
                er.ID = -25;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        void pLogin(object param, out object err)
        {
            ErrorType er = new ErrorType();
            er.ID = 27;
            er.Process = "Login";
            try
            {
                UserType ut = (UserType)param;
                pProfile = new UserType();
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT * FROM tblUsers WHERE fUsername='" + ut.Username + "'");
                if (db.Count == 1)
                {
                    pProfile.Username = db.RecordAt(0, "fUsername");
                    pProfile.Password = db.RecordAt(0, "fPassword");
                    if (pProfile.Password.Equals(ut.Password))
                    {
                        pProfile.logged = true;
                    }
                    else
                    {
                        pProfile.logged = false;
                    }
                }
                else
                {
                    pProfile.logged = false;
                }
            }
            catch (Exception ex)
            {
                er.ID = -27;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        //Async Operation
        delegate void AsyncOp(object param, out object err);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (((ErrorType)er).ID > 0)
            {
                OnProcessCompleted(((ErrorType)er).ID, ((ErrorType)er).Message);
            }
            else
            {
                OnProcessError(((ErrorType)er).ID, ((ErrorType)er).Message);
            }
        }

        public void GetUserList()
        {
            AsyncOp ao = new AsyncOp(pGetUserList);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(null, out err, ac, null);
        }
        public void GetUser(string Username)
        {
            AsyncOp ao = new AsyncOp(pGetUser);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(Username, out err, ac, null);
        }
        public void Add(UserType ut)
        {
            AsyncOp ao = new AsyncOp(pAdd);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(ut, out err, ac, null);
        }
        public void Update(UserType[] ut)
        {
            AsyncOp ao = new AsyncOp(pUpdate);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(ut, out err, ac, null);
        }
        public void Delete(string Username)
        {
            AsyncOp ao = new AsyncOp(pDelete);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(Username, out err, ac, null);
        }
        public void Login(UserType ut)
        {
            AsyncOp ao = new AsyncOp(pLogin);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(ut, out err, ac, null);
        }
        public string[] Users
        {
            get { return pUser; }
        }
        public UserType User
        {
            get { return pProfile; }
        }
        //Event
        public event ModuleEventsHandler ProcessCompleted;
        public event ModuleEventsHandler ProcessError;
        protected void OnProcessError(int procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected void OnProcessCompleted(int procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
    }
    public class StockEntry
    {
        private string[] pBarcodes;
        private DataTable pStocks = new DataTable();
        private static string svr = Common.lServer, dbq = Common.lDatabase, uid = Common.lUID, pwd = Common.lPWD;
        public StockEntry()
        {
        }

        //Sync Operation
        void pAdd(object param, out object err)
        {
            ProcessType er = new ProcessType();
            er.ID = "StockEntry";
            try
            {
                StockType st = (StockType)param;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                db.RecordQuery("SELECT fBarcode, fDescription,fUnit FROM tblProducts WHERE fBarcode='" + st.fBarcode + "'");
                if (db.Count == 1)
                {
                    int mult = 1;
                   
                    string Bar = db.RecordAt(0, "fBarcode");
                    string Dec = db.RecordAt(0, "fDescription");
                    string Unt = db.RecordAt(0, "fUnit");
                    db.RecordQuery("SELECT * FROM tblStocks WHERE fBarcode='" + Bar + "'");
                    if (st.fQty > 0)
                    {
                        for (int i = 0; i < (st.fQty * mult); i++)
                        {
                            DataRow dr = db.GetParameter();
                            dr["fBarcode"] = Bar;
                            dr["fDescription"] = Dec;
                            db.Records.Add(dr);
                        }
                        db.Update(ConflictOption.CompareRowVersion);
                        db.RecordQuery("SELECT * FROM tblStocks2 WHERE fBarcode='" + Bar + "'");
                        if (db.Count == 0)
                        {
                            DataRow dr = db.GetParameter();
                            dr["fDescription"] = Dec;
                            dr["fBarcode"] = Bar;
                            dr["fQty"] = "0";
                            dr["fUnit"] = Unt;
                            db.Records.Add(dr);
                            db.Update(ConflictOption.CompareRowVersion);
                        }
                    }
                    else if ((st.fQty < 0) && (db.Count > 0))
                    {
                        for (int i = 0; i < System.Math.Abs(st.fQty * mult); i++)
                        {
                            db.Records[i].Delete();
                        }
                        db.Update(ConflictOption.CompareAllSearchableValues);
                    }

                }
                else
                {
                    er.HasError = true;
                    er.Message = "Barcode not found.";
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        void pGetBarcode(object param, out object err)
        {
            ProcessType er = new ProcessType();
            er.ID = "BarcodeList";
            try
            {
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                string str = (string)param;
                db.RecordQuery("SELECT fBarcode FROM tblProducts WHERE fBarcode LIKE '%" + str + "%' ORDER BY fBarcode ASC LIMIT 0, 10");
                pBarcodes = new string[db.Count];
                for (int i = 0; i < pBarcodes.Length; i++)
                {
                    pBarcodes[i] = db.RecordAt(i, "fBarcode");
                }
                return;
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                err = er;
            }
        }
        void pGetStocks(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "GetStocks";
            try
            {
                string str = (string)p;
                uDatabase db = new uDatabase();
                db.Connect(uCoreClasses.OdbcVersion.v510, svr, dbq, uid, pwd);
                //db.RecordQuery("SELECT fBarcode, fDescription FROM tblProducts WHERE fBarcode IN(SELECT DISTINCT fBarcode FROM tblStocks) AND fDescription LIKE '%" + str + "%' ORDER BY fDescription ASC");
                db.RecordQuery("SELECT DISTINCT fDescription, fBarcode FROM tblStocks2 WHERE fBarcode LIKE '%" + str + "%'");
                if (db.Count > 0)
                {
                    pStocks.Clear();
                    pStocks.Rows.Clear();
                    pStocks.Columns.Clear();
                    pStocks.Columns.Add("Description");
                    pStocks.Columns.Add("WholeStock");
                    pStocks.Columns.Add("RetailStock");
                    string[] bcode = new string[db.Count];
                    for (int i = 0; i < db.Count; i++)
                    {
                        bcode[i] = db.RecordAt(i, "fBarcode");
                        DataRow dr = pStocks.NewRow();
                        dr["Description"] = db.RecordAt(i, "fDescription");
                        dr["WholeStock"] = "0";
                        dr["RetailStock"] = "0";
                        pStocks.Rows.Add(dr);
                    }
                    
                    for (int i = 0; i < bcode.Length; i++)
                    {
                        //db.RecordQuery("SELECT tblStocks.fBarcode, tblStocks2.fQty, tblStocks2.fUnit FROM tblStocks, tblStocks2 WHERE tblStocks.fBarcode='" + bcode[i] + "' AND tblStocks2.fBarcode='" + bcode[i] + "'");
                        db.RecordQuery("SELECT * FROM tblStocks WHERE fBarcode='" + bcode[i] + "'");
                        pStocks.Rows[i]["WholeStock"] = db.Count.ToString();
                        db.RecordQuery("SELECT * FROM tblStocks2 WHERE fBarcode='" + bcode[i] + "'");
                        if (db.Count >= 1)
                        {
                            pStocks.Rows[i]["RetailStock"] = db.RecordAt(0, "fQty") + " " + db.RecordAt(0, "fUnit");
                        }
                        else
                        {
                            pStocks.Rows[i]["RetailStock"] = "0";
                        }
                    }
                    
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }

        }
        //Async Operation
        delegate void AsyncOp(object param, out object err);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (!((ProcessType)er).HasError)
            {
                OnProcessCompleted(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
            else
            {
                OnProcessError(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
        }
        public void Add(StockType stock)
        {
            AsyncOp ao = new AsyncOp(pAdd);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object err;
            IAsyncResult ar = ao.BeginInvoke(stock, out err, ac, null);
        }
        public void GetBarcode(string str)
        {
            AsyncOp ao = new AsyncOp(pGetBarcode);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(str, out er, ac, null);
        }
        public void GetStocks(string desc)
        {
            AsyncOp ao = new AsyncOp(pGetStocks);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(desc, out er, ac, null);
        }
        public string[] Barcodes
        {
            get { return pBarcodes; }
        }
        public DataTable Stocks
        {
            get { return pStocks; }
        }
        //Event
        public event ModuleEventHandler ProcessCompleted;
        public event ModuleEventHandler ProcessError;
        protected virtual void OnProcessError(string procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected virtual void OnProcessCompleted(string procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
    }
    public class ProductContentManager
    {
        //Data Structures
        private DataTable pUt = new DataTable();
        private ContentDetailType cDt = new ContentDetailType();
        //Sync Operation
        void pGetProductTable(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "GetProductTable";
            try
            {
                uDatabase db = new uDatabase();
                string[] str = (string[])p;
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                //db.RecordQuery("SELECT fBarcode, fDescription FROM tblProducts WHERE fBarcode LIKE '%" + str + "%' OR fDescription LIKE '%" + str + "%'");
                if (str[1] == "1")
                {
                    db.RecordQuery("SELECT fBarcode, fDescription FROM tblProducts WHERE (fBarcode LIKE '%" + str[0] + "%' OR fDescription LIKE '%" + str[0] + "%') AND (fUnit='' OR fContent='')");
                }
                else if (str[1] == "0")
                {
                    db.RecordQuery("SELECT fBarcode, fDescription FROM tblProducts WHERE fBarcode LIKE '%" + str[0] + "%' OR fDescription LIKE '%" + str[0] + "%'");
                }
                pUt.Clear();
                pUt.Columns.Clear();
                if (db.Count > 0)
                {
                    pUt.Columns.Add("fBarcode");
                    pUt.Columns.Add("fDescription");

                    for (int i = 0; i < db.Count; i++)
                    {
                        DataRow dr = pUt.NewRow();
                        dr["fBarcode"] = db.RecordAt(i, "fBarcode");
                        dr["fDescription"] = db.RecordAt(i, "fDescription");
                        pUt.Rows.Add(dr);
                    }
                }
                
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        void pGetContentDetail(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "GetContentDetail";
            try
            {
                uDatabase db = new uDatabase();
                string str = (string)p;
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT fBarcode, fUnit, fContent FROM tblProducts WHERE fBarcode='" + str + "'");
                if (db.Count == 1)
                {
                    cDt.fBarcode = str;
                    cDt.fQty = db.RecordAt(0, "fContent");
                    cDt.fUnit = db.RecordAt(0, "fUnit");
                }
                else
                {
                    cDt.fBarcode = str;
                    cDt.fQty = "";
                    cDt.fUnit = "";
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }
        void pSaveDetails(object p, out object e)
        {
            ProcessType er = new ProcessType();
            er.ID = "SaveDetails";
            try
            {
                uDatabase db = new uDatabase();
                ContentDetailType cd = (ContentDetailType)p;
                db.Connect(uCoreClasses.OdbcVersion.v510, Common.lServer, Common.lDatabase, Common.lUID, Common.lPWD);
                db.RecordQuery("SELECT fID, fUnit, fContent FROM tblProducts WHERE fBarcode='" + cd.fBarcode + "'");
                if (db.Count == 1)
                {
                    db.QueryTable.Rows[0]["fUnit"] = cd.fUnit;
                    db.QueryTable.Rows[0]["fContent"] = cd.fQty;

                    db.Update(ConflictOption.CompareRowVersion);
                }
                else
                {
                    er.HasError = true;
                    er.Message = "Multiple record detected.";
                }
            }
            catch (Exception ex)
            {
                er.HasError = true;
                er.Message = ex.Message;
            }
            finally
            {
                e = er;
            }
        }

        //Async Operation
        delegate void AsyncOp(object p, out object e);
        void GenericCB(IAsyncResult ar)
        {
            AsyncOp ao = (AsyncOp)((AsyncResult)ar).AsyncDelegate;
            object er;
            ao.EndInvoke(out er, ar);

            if (!((ProcessType)er).HasError)
            {
                OnProcessCompleted(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
            else
            {
                OnProcessError(((ProcessType)er).ID, ((ProcessType)er).Message);
            }
        }

        public void GetProductTable(string keyword, bool filter)
        {
            AsyncOp ao = new AsyncOp(pGetProductTable);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            string[] str = new string[2];
            str[0] = keyword;
            str[1] = "0";
            if (filter) str[1] = "1";
            
            IAsyncResult ar = ao.BeginInvoke(str, out er, ac, null);
        }
        public void GetContentDetail(string barcode)
        {
            AsyncOp ao = new AsyncOp(pGetContentDetail);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(barcode, out er, ac, null);
        }
        public void SaveDetails(ContentDetailType content)
        {
            AsyncOp ao = new AsyncOp(pSaveDetails);
            AsyncCallback ac = new AsyncCallback(GenericCB);
            object er;
            IAsyncResult ar = ao.BeginInvoke(content, out er, ac, null);
        }
        public DataTable ProductTable
        {
            get { return pUt; }
        }
        public ContentDetailType ContentDetail
        {
            get { return cDt; }
        }

        //Event
        public event ModuleEventHandler ProcessCompleted;
        public event ModuleEventHandler ProcessError;
        protected virtual void OnProcessError(string procCode, string msg)
        {
            if (ProcessError != null) ProcessError(procCode, msg);
        }
        protected virtual void OnProcessCompleted(string procCode, string msg)
        {
            if (ProcessCompleted != null) ProcessCompleted(procCode, msg);
        }
    }
}
